Omit AcroForm field options with an undefined value#1742
Conversation
Passing a field option whose value is `undefined` to `doc.form*()` serialized the key as the literal token `undefined` (e.g. `/SomeKey undefined`), producing an invalid PDF object that strict parsers (PDFium, iText) reject. foliojs#1738 only handled the mapped `value`/`defaultValue` keys; any other undefined option still leaked. Drop entries with an undefined value in `_fieldDict` so such a field serializes identically to one created without the option. Fixes foliojs#1735.
|
Should be fixed in main by f331b16 Can you run against main to test? |
|
Thanks for the pointer! I ran the branch against current f331b16 only normalizes the Object.keys(VALUE_MAP).forEach((key) => {
if (key in options) {
options[VALUE_MAP[key]] = options[key] ?? '';
delete options[key];
}
});Any other option set to So This PR drops any The branch is already on top of current |
|
What is actual use case for passing custom options to formText? |
|
The options usually come from a config object, not hardcoded. When a field is built from user/template config with optional properties, some of them are just absent: const cfg = loadFieldConfig(); // { tooltip?, value?, align? ... }
doc.formText("name", x, y, w, h, {
align: cfg.align, // undefined when not set
value: cfg.value,
});Today an undefined value serializes as the literal |
|
Now i see. align is handled by _resolveJustify but deleted only when not undefined The current approach is a bit weird mutating same options instance, deleting props which is against js best practices. I will take a look to improve the whole process |
|
I did an overhaul of the acroform options handling that should fix this in ffc17b6 It is faster, produces smaller documents and smaller JS bundles If you find any regressions please report |
|
Makes sense — your overhaul (ffc17b6) handles this at the root by restricting to documented mappings, and it's faster/smaller too. Thanks for taking it on! |
Fixes #1735.
Problem
Passing a field option whose value is
undefinedtodoc.form*()causes that key to be serialized as the literal tokenundefined:A name key followed by the bare token
undefinedis not a valid PDF object. Lenient viewers tolerate it, but strict parsers reject it — the issue reports iText RUPS throwingNullPointerException("object is null") on such a field.#1738 ("Normalize nullish AcroForm text values to empty strings") addressed only the mapped
value/defaultValuekeys viaVALUE_MAP. Any other option passed asundefinedstill leaks into the dictionary, so the broader issue #1735 remains.Fix
Drop entries whose value is
undefinedin_fieldDict, right before the dictionary is returned. A field created with an extraundefinedoption then serializes byte-for-byte identically to one created without that option at all. Defined options (including those legitimately set to falsy values like0,false, or"") are untouched.Tests
Added a unit test (
tests/unit/acroform.spec.js) asserting that a field built with{ CustomKey: undefined }contains noundefinedtoken and matches the output of the same field built with{}./CustomKey undefined).